use std::{ptr::null_mut, usize};

use crate::{init::_mi_page_empty, types::{MiPage, MiPageQueue}};


pub const MI_SMALL_WSIZE_MAX: usize = 128;
pub const MI_SMALL_SIZE_MAX: usize = MI_SMALL_WSIZE_MAX * size_of::<usize>();
pub const MI_PAGES_DIRECT: usize = MI_SMALL_WSIZE_MAX + MI_PADDING_WSIZE + 1;

pub const MI_PADDING: usize = 0;
pub const MI_PADDING_SIZE: usize = 0;
pub const MI_PADDING_WSIZE: usize = 0;

pub const MI_INTPTR_SIZE: usize = size_of::<usize>();
pub const MI_SIZE_SIZE: usize = size_of::<usize>();

// pub const MI_PAGE_EMPTY: *mut MiPage = (&mut _mi_page_empty) as *mut MiPage;

// pub const MI_SMALL_PAGES_EMPTY: [*mut MiPage; 128+1] = [MI_PAGE_EMPTY; 128+1];

pub const fn Q_null(sz: usize) -> MiPageQueue {
    MiPageQueue { first: null_mut(), last: null_mut(), block_size: sz }
}

pub const MI_PAGE_QUEUES_EMPTY: [MiPageQueue; 75] = [
    Q_null(1), Q_null(1), Q_null(2), Q_null(3), Q_null(4), Q_null(5), Q_null(6), Q_null(7), Q_null(8), Q_null(10), 
    Q_null(12), Q_null(14), Q_null(16), Q_null(20), Q_null(24), Q_null(28), Q_null(32), Q_null(40), Q_null(48), Q_null(56), Q_null(64), Q_null(80), Q_null(96), Q_null(112), Q_null(128), Q_null(160), Q_null(192), Q_null(224), Q_null(256), Q_null(320), Q_null(384), Q_null(448), Q_null(512), Q_null(640), Q_null(768), Q_null(896), Q_null(1024), Q_null(1280), Q_null(1536), Q_null(1792), Q_null(2048), Q_null(2560), Q_null(3072), Q_null(3584), Q_null(4096), Q_null(5120), Q_null(6144), Q_null(7168), Q_null(8192), Q_null(10240), Q_null(12288), Q_null(14336), Q_null(16384), Q_null(20480), Q_null(24576), Q_null(28672), Q_null(32768), Q_null(40960), Q_null(49152), Q_null(57344), Q_null(65536), Q_null(81920), Q_null(98304), Q_null(114688), Q_null(131072), Q_null(163840), Q_null(196608), Q_null(229376), Q_null(262144), Q_null(327680), Q_null(393216), Q_null(458752), Q_null(524288), Q_null(655360), Q_null(786432)
];

pub const MI_SMALL_OBJ_SIZE_MAX : usize = MI_SMALL_PAGE_SIZE/4;   // 16KiB
pub const MI_MEDIUM_OBJ_SIZE_MAX: usize = MI_MEDIUM_PAGE_SIZE/4;  // 128KiB
pub const MI_LARGE_OBJ_SIZE_MAX : usize = MI_LARGE_PAGE_SIZE/2;   // 2MiB
pub const MI_LARGE_OBJ_WSIZE_MAX: usize = MI_LARGE_OBJ_SIZE_MAX/MI_INTPTR_SIZE;

// Derived constants
pub const MI_SEGMENT_SIZE            : usize = 1<<MI_SEGMENT_SHIFT;
pub const MI_SEGMENT_ALIGN           : usize = MI_SEGMENT_SIZE;
pub const MI_SEGMENT_MASK            : usize = MI_SEGMENT_ALIGN - 1;
pub const MI_SMALL_PAGE_SIZE         : usize = 1<<MI_SMALL_PAGE_SHIFT;
pub const MI_MEDIUM_PAGE_SIZE        : usize = 1<<MI_MEDIUM_PAGE_SHIFT;
pub const MI_LARGE_PAGE_SIZE         : usize = 1<<MI_LARGE_PAGE_SHIFT;
pub const MI_SMALL_PAGES_PER_SEGMENT : usize = MI_SEGMENT_SIZE/MI_SMALL_PAGE_SIZE;
pub const MI_MEDIUM_PAGES_PER_SEGMENT: usize = MI_SEGMENT_SIZE/MI_MEDIUM_PAGE_SIZE;
pub const MI_LARGE_PAGES_PER_SEGMENT : usize = MI_SEGMENT_SIZE/MI_LARGE_PAGE_SIZE;

pub const MI_SMALL_PAGE_SHIFT : usize = 13 + MI_INTPTR_SHIFT;      // 64KiB
pub const MI_MEDIUM_PAGE_SHIFT: usize =  3 + MI_SMALL_PAGE_SHIFT;  // 512KiB
pub const MI_LARGE_PAGE_SHIFT : usize =  3 + MI_MEDIUM_PAGE_SHIFT; // 4MiB
pub const MI_SEGMENT_SHIFT    : usize =  MI_LARGE_PAGE_SHIFT;      // 4MiB -- must be equal to `MI_LARGE_PAGE_SHIFT`

pub const MI_INTPTR_BITS: usize = MI_INTPTR_SIZE*8;
pub const MI_SIZE_BITS: usize = MI_SIZE_SIZE*8;
pub const MI_KiB: usize = 1024;
pub const MI_MiB: usize = MI_KiB*MI_KiB;
pub const MI_GiB: usize = MI_MiB*MI_KiB;

pub const MI_INTPTR_SHIFT: usize = if usize::MAX > i64::MAX as usize { 4 } else if usize::MAX == i64::MAX as usize { 3 } else { 2 };
